import inspect, os, imp, py_compile, string, sys, re

def compile_modules(folder):
    """
    Compiles all the modules in a folder.
    """
    files = os.listdir(folder)
    for file in files:
        path = os.path.join(folder, file)
        if os.path.splitext(file)[1] == '.py':
            py_compile.compile(path)

def get_objects(module, path):
    """
    Returns all the functions and classes defined in a module.
    ""    """
    if module.__file__ == path:
        
        l = getattr(module, '__all__')
        if l is None:
            return []
        
#        l = dir(module)
        objects = []
        for obj in l:
            obj = getattr(module, obj)
            if inspect.isclass(obj) | inspect.isfunction(obj):
                objects.append(obj)
    else:
        objects = []
    return objects

def process_function(obj):
    """
    Returns the docstring of a function.
    """
    name = obj.__name__
    doc = inspect.getdoc(obj)
    process_template('function', name, doc)

def process_class(obj):
    """
    Returns the docstring of a class.
    """
    name = obj.__name__
    doc = inspect.getdoc(obj)
    process_template('class', name, doc)
    l = dir(obj)
    for method in l:
        method = getattr(obj, method)
        if inspect.ismethod(method):
            process_method(method)
    
def process_method(obj):
    """
    Returns the docstring of a method.
    """
    name = obj.__name__
    doc = inspect.getdoc(obj)
    process_template('method', name, doc)

def process(obj):
    if inspect.isclass(obj):
        process_class(obj)
    if inspect.isfunction(obj):
        process_function(obj)

def process_template(type, name, doc):
    temp = open('reftemplates/'+type+'.txt', 'r')
    lines = temp.readlines()
    temp.close()
    result = "".join(lines)
    result = string.replace(result, '{name}', name)
    if doc is None:
        doc = "No documentation yet."
    result = string.replace(result, '{doc}', doc)
    print result

def write_doc(docfolder, obj):
#    if inspect.isclass(obj):
#        docfile = "Ref"
#    if inspect.isfunction(obj):
#        docfile = "Ref"
#    
    docfile = string.capwords(obj.__name__)
    docfile = string.replace(docfile, '_', ' ')
    docfile = string.capwords(docfile)
    docfile = string.replace(docfile, ' ', '')
    docfile = "Ref"+docfile+".wiki"
    
    old_stdout = sys.stdout
    file = open(os.path.join(docfolder, docfile), 'w')
    sys.stdout = file
    process(obj)
    sys.stdout = old_stdout
    file.close()
    return docfile

def create_doc(folder, docfolder = "docs", filelist = None):
    compile_modules(folder)
    
    files = os.listdir(folder)
    classes = dict([])
    functions = dict([])
    
    old_stdout = sys.stdout
    reffile = open(os.path.join(docfolder, "Reference.wiki"), 'w')
    sys.stdout = reffile
    
    for file in files:
        name = os.path.splitext(file)[0]
        if (filelist is not None) & (name in filelist.keys()): 
            path = os.path.join(folder, file)
            if os.path.splitext(file)[1] == '.pyc':
#                print "Processing file %s..." % file
                sys.path.append(folder)
                module = imp.load_compiled("module", path)
                objects = get_objects(module, path)
                
                print '=', filelist[name], '='
                print
                
                for obj in objects:
                    process(obj)
#                    docfile = write_doc(docfolder, obj)
#                    if inspect.isclass(obj):
#                        classes[obj.__name__] = os.path.splitext(docfile)[0]
#                    if inspect.isfunction(obj):
#                        functions[obj.__name__] = os.path.splitext(docfile)[0]
                        
#    create_index(docfolder, functions, classes)

    sys.stdout = old_stdout
    reffile.close()

    print "Finished!"

def create_index(docfolder, functions, classes):
    temp = open('reftemplates/ref.txt', 'r')
    lines = temp.readlines()
    result = "".join(lines)
    temp.close()
    
    strfunctions = ""
    
    fkeys = functions.keys()
    fkeys.sort()
    
    fclasses = classes.keys()
    fclasses.sort()
    
    for fun in fkeys:
        strfunctions += "  * [%s] : documentation of `%s`\n" % (functions[fun], fun)
    
    strclasses = ""
    for cls in fclasses:
        strclasses += "  * [%s] : documentation of `%s`\n" % (classes[cls], cls)
    
    result = string.replace(result, '{functions}', strfunctions)
    result = string.replace(result, '{classes}', strclasses)
    
    file = open(os.path.join(docfolder, 'ReferenceDocumentation.wiki'), 'w')
    file.write(result)
    file.close()

if __name__ == '__main__':
    create_doc('playdoh', 'wiki', {'distfun': "Distributed functions",
                                   'distopt': "Distributed optimization",
                                   'worker': "Running a worker on a distant machine"})
    
    
    